﻿using ModernUILogViewer.Model;
using MvvmFoundation.Wpf;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace ModernUILogViewer.ViewModel
{
    public class StatisticsViewModel : BaseViewModel
    {

        #region Constructor

        public StatisticsViewModel(MainViewModel mainVM)
        {
            this.homeVM = mainVM.HomeVM;

            allLogLevelsCount = Enum.GetValues(typeof(LOG_LEVEL)).Length;

            prop = new PropertyObserver<HomeViewModel>(mainVM.HomeVM);
            prop.RegisterHandler(n => n.FilteredLogEntries, n => UpdateGlobalStatistics());
            prop.RegisterHandler(n => n.LogEntries, n => UpdateIntervalStatistics());
        }
        
        #endregion

        #region Fields

        private readonly PropertyObserver<HomeViewModel> prop;
        private HomeViewModel homeVM;
        private readonly int allLogLevelsCount;
        
        #endregion

        #region Properties

        private IList<LogEntryViewModel> allEntries { get { return homeVM.LogEntries; } }
        private IList<LogEntryViewModel> filteredEntries { get { return homeVM.FilteredLogEntries; } }

        private IList<KeyValuePair<LOG_LEVEL, int>> allEntriesKV;

        public IList<KeyValuePair<LOG_LEVEL, int>> AllEntriesKV
        {
            get { return allEntriesKV; }
            set
            {
                allEntriesKV = value;
                RaisePropertyChanged(() => AllEntriesKV);
            }
        }


        private IList<KeyValuePair<LOG_LEVEL, int>> filteredEntriesKV;

        public IList<KeyValuePair<LOG_LEVEL, int>> FilteredEntriesKV
        {
            get { return filteredEntriesKV; }
            set
            {
                filteredEntriesKV = value;
                RaisePropertyChanged(() => FilteredEntriesKV);
            }
        }

        private IList<KeyValuePair<string, int>>[] dateEntriesKV;

        public IList<KeyValuePair<string, int>>[] DateEntriesKV
        {
            get { return dateEntriesKV; }
            set
            {
                dateEntriesKV = value;
                RaisePropertyChanged(() => DateEntriesKV);
            }
        }

        //private LOG_LEVEL selectedLevel;

        //public LOG_LEVEL SelectedLevel
        //{
        //    get { return selectedLevel; }
        //    set { 
        //        selectedLevel = value;
        //        RaisePropertyChanged(() => SelectedLevel);
        //    }
        //}
        
        
        #endregion

        #region Methods

        private void UpdateGlobalStatistics()
        {
            allEntriesKV = new List<KeyValuePair<LOG_LEVEL, int>>();
            filteredEntriesKV = new List<KeyValuePair<LOG_LEVEL, int>>();

            if (allEntries.Count > 0)
            {
                Func<IEnumerable<LogEntryViewModel>, LOG_LEVEL, KeyValuePair<LOG_LEVEL, int>> funcLevelCount = (list, level) =>
                {
                    return new KeyValuePair<LOG_LEVEL, int>(level, list.Where(o => o.Level == level).Count());
                };

                // foreach level, return a KV of (level / count of entries)
                Enum.GetValues(typeof(LOG_LEVEL)).Cast<LOG_LEVEL>().All
                    (n =>
                    {
                        allEntriesKV.Add(funcLevelCount(allEntries, n));
                        filteredEntriesKV.Add(funcLevelCount(filteredEntries, n));
                        return true;
                    }
                    );
            }

            RaisePropertyChanged(() => AllEntriesKV);
            RaisePropertyChanged(() => FilteredEntriesKV);
        }

        private void UpdateIntervalStatistics()
        {            
            dateEntriesKV = new List<KeyValuePair<string, int>>[allLogLevelsCount];

            IEnumerable<LOG_LEVEL> levels = Enum.GetValues(typeof(LOG_LEVEL)).Cast<LOG_LEVEL>();

            int i = 0;

            foreach (LOG_LEVEL level in levels)
            {
                dateEntriesKV[i] = new List<KeyValuePair<string, int>>();

                // for each level, return a list of KV of (date / entries count)
                IEnumerable<KeyValuePair<string, int>> result = allEntries.Where(x => x.Level == level)
                    .GroupBy(x => x.DTime.Date)
                    .Select(x => new KeyValuePair<string, int>(x.Key.ToString("dd/MM", CultureInfo.InvariantCulture), x.Count()));

                // fill array index of List<KeyValuePair>
                dateEntriesKV[i] = result.ToList();

                i++;
            }

            RaisePropertyChanged(() => DateEntriesKV);

        }

        //void UpdateIntervalStatisticsSubjectExecute()
        //{
        //    UpdateIntervalStatistics();
        //}
        
        #endregion

        #region Commands

        //public ICommand UpdateIntervalStatisticsSubject { get { return new MvvmFoundation.Wpf.RelayCommand(UpdateIntervalStatisticsSubjectExecute); } }

        #endregion
    }
}
